﻿using System;
using System.Runtime.InteropServices;
using System.Web;
using System.Web.SessionState;
using Microsoft.IdentityModel.Protocols.WSFederation;
using Microsoft.SharePoint;

namespace CodeCounsel.SharePoint2010.DigiD
{
    [Guid("5fd20530-77c4-4da4-a6d4-b5c563fecce5")]
    public class LoginHandler 
        : IHttpHandler, IRequiresSessionState
    {
        public bool IsReusable
        {
            get { return true; }
        }

        public void ProcessRequest(HttpContext context)
        {
            context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
            context.Response.Cache.SetNoStore();
            context.Response.Cache.SetExpires(DateTime.MinValue);
            try
            {
                string action = context.Request.QueryString[WSFederationConstants.Parameters.Action];
                if (action == WSFederationConstants.Actions.SignIn)
                {
                    SignIn(context);
                }
                else if (action == WSFederationConstants.Actions.SignOut)
                {
                    SignOut(context);
                }
                
            }
            catch(DigiDException e)
            {
               context.Response.StatusCode = 500;
               context.Response.Write(e.Message);
               context.Response.Write(Environment.NewLine);
               context.Response.Write(e.GetBaseException().Message);
               context.Response.End();
            }
            catch (Exception)
            {
                context.Response.StatusCode = 500;
                context.Response.End();
            }
        }

        void SignIn(HttpContext context)
        {
            // Parse the request URI into an object
            SignInRequestMessage requestMessage = (SignInRequestMessage)WSFederationMessage.CreateFromUri(context.Request.Url);
            // The identifier 'realm' is passed as the wtrealm query string parameter.
            // The DigiD settings are associated with the realm as SharePoint can
            // create a realm per site collection in the trusted identity token issuer 
            // configuration.
            DigiDSettings settings = DigiDService.Local.DigiDSettings[requestMessage.Realm];
            if (settings == null)
            {
                throw new DigiDException("Realm is not configured for DigiD authentication.");
            }
            try
            {
                // Do a lame transformation for the location where DigiD should redirect the user back
                Uri digiDAuthenticateResponseUrl = new Uri(context.Request.Url.GetLeftPart(
                    UriPartial.Path).ToLower().Replace("login.ashx", "digid.ashx"));
                // Call the DigiD service to let them know a user is coming
                InitWebRequest request = new InitWebRequest(digiDAuthenticateResponseUrl, settings);
                InitWebResponse response = request.GetResponse();
                // Store the SharePoint STS request in a cache so that it can be
                // retrieved when DigiD redirects the user back to us.
                SignInRequestCache.Add(response.RequestID, requestMessage);
                // Redirect the user
                Redirector.Redirect(context, new Uri(response.ASelectUrl),
                    queryParameters =>
                    {
                        queryParameters[Schema.RequestID] = response.RequestID;
                        queryParameters[Schema.ASelectServer] = response.ASelectServer;
                    });
            }
            catch (DigiDException)
            {
                throw;
            }
        }

        void SignOut(HttpContext context)
        {
        }
    }
}
